﻿using Aliyun.OSS;
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using SafeSyncPro;

public class AliyunOSSUploader
{
    // 阿里云OSS的Endpoint
    private static string endpoint = "oss-cn-beijing.aliyuncs.com";

    // 阿里云的AccessKeyId
    private static string accessKeyId = "LTAI5tBjCBz6F1KCnJ8vMVWj";

    // 阿里云的AccessKeySecret
    private static string accessKeySecret = "DdpAIpUFTgz06hOhp67CubK4YbU2YR";

    // 存储桶名称
    private static string bucketName = "safe-sync-pro";

    // 创建一个OSS客户端
    private static OssClient client = new OssClient(endpoint, accessKeyId, accessKeySecret);

    // 上传文件的方法
    public static void UploadFile(string filePath, string objectName)
    {
        try
        {
            // 使用FileStream读取文件
            using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                fs.Position = 0; // 确保流的起始位置
                // 创建PutObjectRequest对象，指定上传的存储桶名称、对象名称和文件流
                PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, fs);

                // 调用PutObject方法进行文件上传
                client.PutObject(putObjectRequest);

                // 上传成功后输出日志
                Console.WriteLine($"文件'{objectName}'上传成功！");            }
        }
        catch (Exception ex)
        {
            // 如果上传过程中发生异常，捕获并输出异常信息
            Console.WriteLine($"上传文件时出错: {ex.Message}");        }
    }

    // 上传文件夹的方法
    public static void UploadDirectory(string directoryPath, string objectPrefix = "")
    {
        string DirectoryPrefix = objectPrefix + Path.GetFileName(directoryPath) + "/";
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, DirectoryPrefix, new MemoryStream());
        client.PutObject(putObjectRequest);
        Console.WriteLine($"目录 '{DirectoryPrefix}' 已创建！");
        // 获取当前目录下的所有文件（不包括隐藏文件）
        var files = Directory.GetFiles(directoryPath, "*", SearchOption.TopDirectoryOnly)
                              .Where(f => (new FileInfo(f).Attributes & FileAttributes.Hidden) == 0)
                              .ToList();
        objectPrefix += Path.GetFileName(directoryPath) + "/";

        // 创建任务列表用于并行处理
        var tasks = new List<Task>();

        // 遍历当前文件夹中的所有文件并上传
        foreach (var file in files)
        {
            tasks.Add(Task.Run(() =>
            {
                using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
                {
                    // 生成相对于目录的相对路径，并生成 OSS 中的 object 名称
                    string objectName = objectPrefix + Path.GetFileName(file);
                    // 上传文件
                    putObjectRequest = new PutObjectRequest(bucketName, objectName, fs);
                    client.PutObject(putObjectRequest);
                    Console.WriteLine($"文件 '{objectName}' 上传成功！");
                }
            }));
        }

        // 获取当前目录下的所有子目录
        var subDirectories = Directory.GetDirectories(directoryPath);

        foreach (var subDirectory in subDirectories)
        {
            tasks.Add(Task.Run(() =>
            {
                // 递归调用 UploadDirectory 方法，继续上传子目录中的文件
                UploadDirectory(subDirectory, objectPrefix);
            }));
        }

        // 等待所有任务完成
        Task.WaitAll(tasks.ToArray());
    }



    // 列出存储桶中的文件和文件夹
    public static (List<string> Folders, List<string> Files) ListObjects(string prefix = "")
    {
        try
        {
            var request = new ListObjectsRequest(bucketName)
            {
                Prefix = prefix,
                Delimiter = "/" // 使用分隔符区分文件夹和文件
            };

            var result = client.ListObjects(request);

            // 获取文件夹列表
            var folders = result.CommonPrefixes.ToList();

            // 获取文件列表
            var files = result.ObjectSummaries.Select(obj => obj.Key).Where(key => !key.EndsWith("/")).ToList();

            return (folders, files);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"获取OSS对象列表时出错: {ex.Message}");
            return (new List<string>(), new List<string>());
        }
    }

    public static void DeleteFolder(string folderPath)
    {
        var objectsToDelete = client.ListObjects(new ListObjectsRequest(bucketName)
        {
            Prefix = folderPath
        }).ObjectSummaries.Select(o => o.Key).ToList();

        foreach (var obj in objectsToDelete)
        {
            client.DeleteObject(bucketName, obj);
            Console.WriteLine($"删除: {obj}");
        }
    }

    public static void SyncFolders(string localPath, string ossPath)
    {
        // 列出云端文件和文件夹
        var (ossFolders, ossFiles) = ListObjects(ossPath);

        // 获取本地文件和文件夹
        var localFiles = Directory.GetFiles(localPath, "*", SearchOption.TopDirectoryOnly).ToList();
        var localFolders = Directory.GetDirectories(localPath).ToList();

        // 上传本地文件
        foreach (var localFile in localFiles)
        {
            string fileName = Path.GetFileName(localFile);
            string ossFilePath = $"{ossPath.TrimEnd('/')}/{fileName}";

            if (ossFiles.Contains(ossFilePath))
            {
                Console.WriteLine($"跳过文件: {fileName}");
            }
            else
            {
                UploadFile(localFile, ossFilePath);
            }
        }

        // 上传本地文件夹
        foreach (var localFolder in localFolders)
        {
            string folderName = Path.GetFileName(localFolder);
            string ossFolderPath = $"{ossPath.TrimEnd('/')}/{folderName}/";

            if (ossFolders.Contains(ossFolderPath))
            {
                // 递归检查云端文件夹与本地文件夹
                SyncFolders(localFolder, ossFolderPath);
            }
            else
            {
                UploadDirectory(localFolder, ossPath);
            }
        }

        // 删除云端多余的文件
        foreach (var ossFile in ossFiles)
        {
            string fileName = Path.GetFileName(ossFile);
            string localFilePath = Path.Combine(localPath, fileName);

            if (!File.Exists(localFilePath))
            {
                client.DeleteObject(bucketName, ossFile);
                Console.WriteLine($"删除多余文件: {ossFile}");
            }
        }

        // 删除云端多余的文件夹
        foreach (var ossFolder in ossFolders)
        {
            string folderName = ossFolder.TrimEnd('/').Substring(ossFolder.TrimEnd('/').LastIndexOf('/') + 1);
            string localFolderPath = Path.Combine(localPath, folderName);

            if (!Directory.Exists(localFolderPath))
            {
                DeleteFolder(ossFolder);
                Console.WriteLine($"删除多余文件夹: {ossFolder}");
            }
        }
    }
}
